package com.backend.common.utils;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

/**
 * Excel导入导出工具类
 */
@Slf4j
public class ExcelUtils {

    /**
     * Excel导入结果
     */
    @Data
    public static class ImportResult<T> {
        private int total;
        private int success;
        private int failed;
        private List<String> errorMessages = new ArrayList<>();
        private List<T> successData = new ArrayList<>();
        private List<T> failData = new ArrayList<>();
    }

    /**
     * 导出Excel
     *
     * @param data      导出的数据
     * @param fileName  文件名
     * @param sheetName sheet名
     * @param clazz     导出对象类型
     * @param <T>       泛型
     * @return ResponseEntity
     */
    public static <T> ResponseEntity<byte[]> export(List<T> data, String fileName,
                                                  String sheetName, Class<T> clazz) {
        try {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

            // 导出数据
            EasyExcel.write(outputStream, clazz)
                    .excelType(ExcelTypeEnum.XLSX)
                    .sheet(sheetName)
                    .doWrite(data);

            byte[] excelBytes = outputStream.toByteArray();

            String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8).replaceAll("\\+", "%20");
            return ResponseEntity.ok()
                    .contentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"))
                    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=utf-8''" + encodedFileName + ".xlsx")
                    .contentLength(excelBytes.length)
                    .body(excelBytes);

        } catch (Exception e) {
            log.error("Excel导出失败", e);
            throw new RuntimeException("Excel导出失败：" + e.getMessage(), e);
        }
    }

    /**
     * 导入Excel
     *
     * @param file      Excel文件
     * @param clazz     导入对象类型
     * @param validator 数据校验器
     * @param <T>       泛型
     * @return 导入结果
     */
    public static <T> ImportResult<T> importExcel(MultipartFile file, Class<T> clazz, Consumer<T> validator) {
        ImportResult<T> result = new ImportResult<>();

        try {
            EasyExcel.read(file.getInputStream(), clazz, new AnalysisEventListener<T>() {
                @Override
                public void invoke(T data, AnalysisContext context) {
                    try {
                        // 执行数据校验
                        if (validator != null) {
                            validator.accept(data);
                        }
                        result.getSuccessData().add(data);
                        result.setSuccess(result.getSuccess() + 1);
                    } catch (Exception e) {
                        result.getFailData().add(data);
                        result.setFailed(result.getFailed() + 1);
                        result.getErrorMessages().add(String.format("第%d行: %s", context.readRowHolder().getRowIndex() + 1, e.getMessage()));
                    }
                }

                @Override
                public void doAfterAllAnalysed(AnalysisContext context) {
                    result.setTotal(result.getSuccess() + result.getFailed());
                    log.info("Excel解析完成，总数：{}，成功：{}，失败：{}", 
                            result.getTotal(), result.getSuccess(), result.getFailed());
                }
            }).sheet().doRead();

        } catch (IOException e) {
            log.error("Excel导入失败", e);
            throw new RuntimeException("Excel导入失败：" + e.getMessage());
        }

        return result;
    }

    /**
     * 生成导入模板
     *
     * @param fileName  文件名
     * @param sheetName sheet名
     * @param clazz     模板类型
     * @param <T>       泛型
     * @return ResponseEntity
     */
    public static <T> ResponseEntity<byte[]> generateTemplate(String fileName,
                                                            String sheetName, Class<T> clazz) {
        return export(new ArrayList<>(), fileName, sheetName, clazz);
    }
} 